"""Get a list of DataWarehouse issues requiring attention."""
import argparse
import datetime
import os
import re
from xmlrpc.client import Fault

import bugzilla
from cki_lib import gitlab
from cki_lib import logger
from cki_lib import misc
from cki_lib import yaml
import datawarehouse
import dateutil.parser
import sentry_sdk

BUGZILLA_URL = os.environ.get('BUGZILLA_URL', 'https://bugzilla.redhat.com')
BUGZILLA_API_KEY = os.environ.get('BUGZILLA_API_KEY')
DATAWAREHOUSE_URL = os.environ.get('DATAWAREHOUSE_URL', 'https://datawarehouse.cki-project.org')
DATAWAREHOUSE_TOKEN = os.environ.get('DATAWAREHOUSE_TOKEN')
GITLAB_URLS = yaml.load(contents=os.environ.get('GITLAB_TOKENS', '{}')).keys()

DW = datawarehouse.Datawarehouse(DATAWAREHOUSE_URL, DATAWAREHOUSE_TOKEN)
BZ = bugzilla.Bugzilla(BUGZILLA_URL, api_key=BUGZILLA_API_KEY)

LOGGER = logger.get_logger('cki.cki_tools.datawarehouse.issue_maintenance')


def process_issue(issue, older_than, only_closed=False):
    """Process each issue and print the message accordingly."""
    closed = False

    if any(url in issue.ticket_url for url in GITLAB_URLS):
        try:
            _, gl_object = gitlab.parse_gitlab_url(issue.ticket_url)
        except gitlab.gitlab.exceptions.GitlabError:
            LOGGER.warning(
                'Could not retrieve GitLab information. '
                'Make sure GITLAB_TOKENS is configured and you have permission to access %s',
                issue.ticket_url
            )
        else:
            if isinstance(gl_object, gitlab.gitlab.v4.objects.ProjectIssue):
                closed = gl_object.state == 'closed'

    elif BUGZILLA_URL in issue.ticket_url:
        bug_id = re.findall(r'id=(\d+).*', issue.ticket_url)[0]
        try:
            bz_ticket = BZ.getbug(bug_id)
        except Fault:
            LOGGER.warning(
                'Could not retrieve Bugzilla information. '
                'Make sure BUGZILLA_API_KEY is configured and you have permission to access %s',
                issue.ticket_url
            )
        else:
            closed = not bz_ticket.is_open

    elif only_closed:
        LOGGER.warning('Unknown ticket_url, can not determine status: %s', issue.ticket_url)

    ignore = (
        # Only show closed tickets
        (only_closed and not closed) or
        # Ticket is not closed and hasn't been tagged yet.
        (not closed and not issue.last_seen) or
        # Ticket is not closed and was tagged after the $since value.
        (not closed and dateutil.parser.parse(issue.last_seen) > older_than)
    )

    if ignore:
        return

    last_seen_ago = (
        (datetime.datetime.now(tz=datetime.timezone.utc) -
         dateutil.parser.parse(issue.last_seen)).days
        if issue.last_seen else None
    )

    msg = (
        str(issue.id),
        f"{last_seen_ago} days ago" if last_seen_ago else "Not tagged",
        "**CLOSED**" if closed else "",
        f"{DATAWAREHOUSE_URL}/issue/{issue.id}",
        issue.description,
    )
    print(' - '.join(msg))


def parse_args(args=None):
    """Parse arguments."""
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--since', type=misc.parse_timedelta, default='4 weeks',
                        help='Show issues not linked to a checkout in this period of time')
    parser.add_argument('--only-closed', action='store_true',
                        help='Only show issues with a closed ticket')
    return parser.parse_args(args)


def main(since, closed=False):
    """Loop over DW issues and look for issues requiring attention."""
    older_than = datetime.datetime.now(tz=datetime.timezone.utc) - since

    for issue in DW.issue.list(iterator=True, limit=200):
        if issue.resolved:
            continue
        process_issue(issue, older_than, closed)


if __name__ == '__main__':
    misc.sentry_init(sentry_sdk)
    arguments = parse_args()
    main(arguments.since, arguments.only_closed)
